import paramiko
import glog
import re

# ip_list=[
#     "10.112.212.170", #1
#     "10.112.141.111", #2
#     "10.112.46.218", #3
#     "10.112.87.81", #4
#     "10.112.124.46", #5
#     "10.112.149.148", #6
#     "10.112.59.93", #7
#     "10.112.212.64", #8
#     "10.112.81.61", #9
#     "10.112.23.182", #10
#     "10.112.251.26", #11
#     "10.112.15.2", #12
#     "10.112.194.140", #13
#     "10.112.163.129" #14
# ]

user = "buptuser"
ip_list=[
    ["10.112.85.15", 23421, "buptuser@net1.bupt"],#net1
    ["10.112.53.32", 23421, "buptuser@net2.bupt"],#net2
    ["10.112.0.98", 23421, "buptuser@net3.bupt"],#net3
    ["10.112.116.106", 2222, "ptdn@bupt.R930"],#R930
    ["10.112.202.198", 23421, "smart_route"],#R930
]


controller_ip = "10.112.2.67"
controller_port="6633"

remote_dir = "./"


class SudoClient(paramiko.SSHClient):
    def __init__(self, pwd) -> None:
        super().__init__()
        self.pwd = pwd
    def sudo_exec_command(self, cmd: str):
        stdin, stdout, stderr = self.exec_command(f'sudo -S bash -c "{cmd}"')
        stdin.write(self.pwd + '\n')
        stdin.flush()
        out = stdout.read().decode()
        err = stderr.read().decode()
        print(out)
        print(err)
        return out,err


def create_clients():
    clients = []
    for ip,ssh_port,pwd in ip_list:
        client = SudoClient(pwd)
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            glog.info("Connecting to %s"%ip)
            client.connect(ip, ssh_port, user, pwd)
            clients.append((ip, client))
        except Exception:
            glog.fatal(f'cannot connect to {ip}')
    return clients

def upload_ovs(clients):
    ovs_path = input("输入ovs包名称:")
    for ip, client in clients:
        print(ip)
        try:
            sftp = client.open_sftp()
            sftp.put(ovs_path, ovs_path)
            remote_file_stat = sftp.stat(ovs_path)
            if remote_file_stat:
                glog.info(ovs_path+"传输成功")
            else:
                glog.info(ovs_path+"传输失败")
        finally:
            sftp.close()

def install_ovs(clients):
    ovs_deb = input("输入ovs包名称:")
    command = "dpkg -i " + ovs_deb
    for ip, client in clients:
        print(ip)
        client.sudo_exec_command(command)

def upload_scripts(clients):
    scripts=["dpdk_config.py", "dpdk-devbind.py", "ovs_config.py", "ovs-slice_action.zip"]
    for ip, client in clients:
        print(ip)
        try:
            sftp = client.open_sftp()
            for script in scripts:
                remote_path = remote_dir+script
                sftp.put(script, remote_path)
                remote_file_stat = sftp.stat(remote_path)
                if remote_file_stat:
                    glog.info(script+"传输成功")
                    client.sudo_exec_command('chmod +x ' + remote_path)
                else:
                    glog.info(script+"传输失败")
        finally:
            sftp.close()


def dpdk_config(clients):
    for ip, client in clients:
        print(ip)
        client.sudo_exec_command(remote_dir + 'dpdk_config.py')

def restart_ovs(clients):
    for ip, client in clients:
        print(ip)
        client.sudo_exec_command('ovs-ctl stop && ovs-ctl start')

def ovs_config(clients):
    for ip, client in clients:
        print(ip)
        client.sudo_exec_command(remote_dir +'ovs_config.py')

def stop_ovs(clients):
    for ip, client in clients:
        print(ip)
        client.sudo_exec_command('ovs-ctl stop')

def input_command(clients):
    command = input()
    print("command: "+command)
    for ip, client in clients:
        print(ip)
        client.sudo_exec_command(command)

def set_dpid(clients):
    i=1
    for ip, client in clients:
        print(ip)
        command = 'ovs-vsctl set bridge br0 other_config:datapath-id='+'{:016X}'.format(i)
        client.sudo_exec_command(command)
        i+=1

def set_speeds(clients):
    speeds=input("Input speeds: ")
    for ip, client in clients:
        print(f'====================={ip}=============================')
        command = 'ovs-vsctl show'
        out, err = client.sudo_exec_command(command)
        command = "" 
        for line in out.splitlines():
            port_name = re.search(r'dpdk[0-9]', line)
            if(port_name == None):
                continue
            port_name = port_name.group()
            command += 'ovs-vsctl set Interface '+port_name+' options:speeds=' + speeds + '\n'
            client.sudo_exec_command(command)
        command += 'ovs-ctl restart\n'
        print(command)
        client.sudo_exec_command(command)

def set_contrller(clients):
    command = 'ovs-vsctl set-controller br0 '+ controller_ip+":"+controller_port+'\n'
    for ip, client in clients:
        client.sudo_exec_command(command)


def exit(clients):
    for ip, client in clients:
        print(ip)
        client.close()

def main():
    # 操作选项和对应命令
    options = [
        upload_ovs,
        install_ovs,
        upload_scripts,
        dpdk_config,
        restart_ovs,
        set_dpid,
        set_speeds,
        ovs_config,
        stop_ovs,
        set_contrller,
        input_command,
        exit
    ]
    glog.info("Connecting to remote hosts...")
    clients = create_clients()
    stop = False
    hint = ""
    for i, option in zip(range(len(options)),options):
        hint += '[%d] %s\n'%(i, option.__name__)
    try:
        while not stop:
            id = int(input("请输入操作选项的编号:\n"+hint))
            options[id](clients)
            if id == len(options)-1:
                stop = True
    finally:
        exit(clients)        
        


if __name__ == '__main__':
    main()
